﻿using MiniExcelLibs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using xbd.CommunicationLib;
using xbd.DataConvertLib;

namespace xbd.NodeSettings
{
    /// <summary>
    /// 三菱配置解析类
    /// </summary>
    public class MelsecCFG
    {
        public static OperateResult<List<MelsecDevice>> LoadDevice(string path)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);

            List<MelsecDevice> devices = new List<MelsecDevice>();

            try
            {
                foreach (var file in directoryInfo.GetFiles("*.xlsx"))
                {
                    //将单个文件转成单个对象
                    MelsecDevice device = GetDevice(file.Name.Replace(".xlsx", ""));

                    //文件名称验证通过
                    if (device != null)
                    {
                        List<string> sheets = MiniExcel.GetSheetNames(file.FullName);

                        foreach (var sheet in sheets)
                        {
                            //将每个sheet转换成一个Group对象
                            MelsecGroup group = GetGroup(sheet);

                            if (group != null)
                            {
                                try
                                {
                                    group.VarList = MiniExcel.Query<MelsecVariable>(file.FullName, sheet).ToList();

                                    //需要设置变量地址
                                    foreach (var item in group.VarList)
                                    {
                                         item.VarAddress= GetMelsecAddress(group, item);
                                    }

                                    device.GroupList.Add(group);
                                }
                                catch (Exception ex)
                                {
                                    return OperateResult.CreateFailResult<List<MelsecDevice>>("解析变量错误：" + ex.Message);
                                }
                            }
                            else
                            {
                                return OperateResult.CreateFailResult<List<MelsecDevice>>("解析Sheet错误：" + sheet);
                            }
                        }

                        devices.Add(device);
                    }
                    else
                    {
                        return OperateResult.CreateFailResult<List<MelsecDevice>>("解析文件错误：" + file.Name);
                    }


                }
                return OperateResult.CreateSuccessResult(devices);
            }
            catch (Exception ex)
            {
                return OperateResult.CreateFailResult<List<MelsecDevice>>("解析文件故障：" + ex.Message);
            }
        }


        private static MelsecDevice GetDevice(string filename)
        {
            if (filename.Contains("_"))
            {
                string[] info = filename.Split('_');

                if (info.Length == 3)
                {
                    //机台1_192.168.1.16_4196
                    return new MelsecDevice()
                    {
                        DeviceName = info[0],
                        IPAddress = info[1],
                        Port = Convert.ToInt32(info[2]),
                        DataFormat = DataFormat.DCBA
                    };
                }
            }
            return null;
        }

        private static MelsecGroup GetGroup(string sheetname)
        {
            if (sheetname.Contains("_"))
            {
                string[] info = sheetname.Split('_');

                if (info.Length == 3)
                {
                    //sheetName:通信组1_D0_100
                    return new MelsecGroup()
                    {
                        GroupName = info[0],
                        Start =info[1],
                        Count = Convert.ToUInt16(info[2])
                    };
                }
            }
            return null;
        }
    
        private static string GetMelsecAddress(MelsecGroup gp, MelsecVariable variable)
        {
            var result = MelsecAddressAnalysis(gp.Start);
            if(!result.IsSuccess) return string.Empty;  

           return  result.Content1.AreaASCIICode.Replace("*","")+variable.Address;
        }

        /// <summary>
        /// 解析三菱PLC地址
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        private static OperateResult<MelsecMcStoreArea, int> MelsecAddressAnalysis(string address)
        {
            var result = new OperateResult<MelsecMcStoreArea, int>();
            address = address.ToUpper();

            try
            {
                switch (address[0].ToString())
                {
                    case "X":
                        result.Content1 = MelsecMcStoreArea.X;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.X.FromBase);
                        break;
                    case "Y":
                        result.Content1 = MelsecMcStoreArea.Y;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.Y.FromBase);
                        break;
                    case "M":
                        result.Content1 = MelsecMcStoreArea.M;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.M.FromBase);
                        break;
                    case "L":
                        result.Content1 = MelsecMcStoreArea.L;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.L.FromBase);
                        break;
                    case "F":
                        result.Content1 = MelsecMcStoreArea.F;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.F.FromBase);
                        break;
                    case "V":
                        result.Content1 = MelsecMcStoreArea.V;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.V.FromBase);
                        break;
                    case "B":
                        result.Content1 = MelsecMcStoreArea.B;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.B.FromBase);
                        break;
                    case "D":
                        result.Content1 = MelsecMcStoreArea.D;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.D.FromBase);
                        break;
                    case "W":
                        result.Content1 = MelsecMcStoreArea.W;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.W.FromBase);
                        break;
                    case "Z":
                        result.Content1 = MelsecMcStoreArea.Z;
                        result.Content2 = Convert.ToInt32(address.Substring(1), MelsecMcStoreArea.Z.FromBase);
                        break;
                    case "T":
                        result.Content1 = MelsecMcStoreArea.TN;
                        result.Content2 = Convert.ToInt32(address.Substring(2), MelsecMcStoreArea.TN.FromBase);
                        break;
                    case "S":
                        result.Content1 = MelsecMcStoreArea.SN;
                        result.Content2 = Convert.ToInt32(address.Substring(2), MelsecMcStoreArea.SN.FromBase);
                        break;
                    case "CN":
                        result.Content1 = MelsecMcStoreArea.CN;
                        result.Content2 = Convert.ToInt32(address.Substring(2), MelsecMcStoreArea.CN.FromBase);
                        break;
                    default:
                        result.IsSuccess = false;
                        result.Message = "非有效地址:" + address;
                        break;
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.Message = "地址转换错误:" + ex.Message;
            }

            result.IsSuccess = true;
            result.Message = "Success";
            return result;
        }

    }
}
